package app.server.project.main.service.config;

import app.server.project.core.constants.Def;
import app.server.project.core.exception.GlobalException;
import cn.hutool.json.JSONUtil;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Aspect
@Component
@Slf4j
public class LoggingAspect {


    /**
     * 起始时间的时间戳
     */
    private static final ThreadLocal<Long> START_TIME = new ThreadLocal<>();
    private static final long TIME_MAX = 400;

    // 定义切入点表达式，匹配Controller层的方法
    @Pointcut("execution(* app.server.project.main.service.controller..*(..))")
    public void controllerMethods() {
    }

    // 在方法执行前记录日志
    @Before("controllerMethods()")
    public void logBefore(JoinPoint joinPoint) {
        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (attributes != null) {
                HttpServletRequest request = attributes.getRequest();
                log.info("ip:{} http userid:{} 请求 url: {}:参数:{}",
                        request.getRemoteHost(),
                        request.getHeader(Def.UserId),
                        request.getRequestURL().toString(),
                        JSONUtil.formatJsonStr(JSONUtil.toJsonStr(joinPoint.getArgs())));
            }
        } catch (Exception e) {
        }
        START_TIME.set(System.currentTimeMillis());
    }

    // 在方法执行后记录日志（返回结果）
    @AfterReturning(pointcut = "controllerMethods()", returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {
        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (attributes != null) {
                HttpServletRequest request = attributes.getRequest();
                var lastTime = START_TIME.get();
                if (lastTime == null) {
                    lastTime = System.currentTimeMillis();
                }
                var doTime = System.currentTimeMillis() - lastTime;
                if (doTime > TIME_MAX) {
                    log.error("处理时间过长:{}ms ip:{}  http userid:{} 请求 url: {}:请求结果:{}",
                            System.currentTimeMillis() - lastTime,
                            request.getRemoteHost(),
                            request.getHeader(Def.UserId),
                            request.getRequestURL().toString(),
                            JSONUtil.formatJsonStr(JSONUtil.toJsonStr(result)));
                } else {
                    log.info("处理时间:{}ms ip:{}  http userid:{} 请求 url: {}:请求结果:{}",
                            System.currentTimeMillis() - lastTime,
                            request.getRemoteHost(),
                            request.getHeader(Def.UserId),
                            request.getRequestURL().toString(),
                            JSONUtil.formatJsonStr(JSONUtil.toJsonStr(result)));
                }

            }
        } catch (Exception e) {

        }

        START_TIME.remove();
    }

    @AfterThrowing(pointcut = "controllerMethods()", throwing = "ex")
    public void logAfterThrowing(JoinPoint joinPoint, Exception ex) {
        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (attributes != null) {
                HttpServletRequest request = attributes.getRequest();
                var lastTime = START_TIME.get();
                if (lastTime == null) {
                    lastTime = System.currentTimeMillis();
                }
                var doTime = System.currentTimeMillis() - lastTime;
                if (ex instanceof GlobalException) {
                    if (TIME_MAX > doTime) {
                        log.info("处理时间:{}ms  http userid:{} 请求 url: {}:捕获到错误码:{}",
                                doTime,
                                request.getHeader(Def.UserId),
                                request.getRequestURL().toString(),
                                ((GlobalException) ex).getCode());
                    } else {
                        log.error("处理时间过长:{}ms  http userid:{} 请求 url: {}:捕获到错误码:{}",
                                doTime,
                                request.getHeader(Def.UserId),
                                request.getRequestURL().toString(),
                                ((GlobalException) ex).getCode());
                    }

                } else {
                    if (TIME_MAX > doTime) {
                        log.info("处理时间:{}ms  http userid:{} 请求 url: {}:捕获到错误:{}",
                                System.currentTimeMillis() - lastTime,
                                request.getHeader(Def.UserId),
                                request.getRequestURL().toString(),
                                ex);
                    } else {
                        log.error("处理时间:{}ms  http userid:{} 请求 url: {}:捕获到错误:{}",
                                System.currentTimeMillis() - lastTime,
                                request.getHeader(Def.UserId),
                                request.getRequestURL().toString(),
                                ex);
                    }
                }
            }
        } catch (Exception e) {

        }
        START_TIME.remove();
    }


}